package com.cashmama.market.api.application.controller.authentication.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cashmama.market.api.application.controller.authentication.handler.vo.AadhaarCardSaveRequest;
import com.cashmama.market.api.domain.integration.AdvanceAiIntegrationService;
import com.cashmama.market.api.domain.service.AsyncService;
import com.cashmama.market.api.domain.service.UserEventTrackService;
import com.cashmama.market.api.domain.vo.RequestLocalInfo;
import com.cashmama.market.api.domain.vo.aadhaar.AadhaarCardSaveDTO;
import com.cashmama.market.api.infras.config.ApolloConfigUtil;
import com.cashmama.market.api.infras.exception.ApplicationException;
import com.cashmama.market.api.infras.utils.DateUtil;
import com.cashmama.market.api.infras.utils.OSSFixUtils;
import com.cashmama.market.api.infras.utils.StringUtils;
import com.fqgj.common.api.Response;
import com.fqgj.xjd.user.client.UserInfoService;
import com.fqgj.xjd.user.client.UserKycDocumentService;
import com.fqgj.xjd.user.client.UserPanService;
import com.fqgj.xjd.user.client.enums.UserKycTypeEnum;
import com.fqgj.xjd.user.client.enums.UserOcrTypeEnum;
import com.fqgj.xjd.user.client.request.UserBase;
import com.fqgj.xjd.user.client.request.UserPanSaveInfo;
import com.fqgj.xjd.user.client.response.UserKycAadhaarInfo;
import com.fqgj.xjd.user.client.response.UserKycDocumentInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @program: market-api
 * @description
 * @author: frank
 * @create: 2020-01-02 14:03
 **/
@Component
public class KycDocumentHandler {

    private final static Logger LOGGER = LoggerFactory.getLogger(KycDocumentHandler.class);

    @Autowired
    private UserPanService userPanService;
    @Autowired
    private AdvanceAiIntegrationService advanceAiIntegrationService;
    @Autowired
    private UserKycDocumentService userKycDocumentService;
    @Autowired
    private ApolloConfigUtil apolloConfigUtil;
    @Autowired
    private AsyncService asyncService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private UserEventTrackService userEventTrackService;

    public void kycDocumentHandler(AadhaarCardSaveRequest request) {
        request.validate();
        request.setCardNo(request.getCardNo().replaceAll("(\\r\\n|\\t|\\\\r|\\\\n\\\\t|\n|\n\t|\r|\r\n|\t)", ""));
        request.setPanCardNo(request.getPanCardNo().replaceAll("(\\r\\n|\\t|\\\\r|\\\\n\\\\t|\n|\n\t|\r|\r\n|\t)", ""));
        request.setCardFrontUrl(OSSFixUtils.fixOssUrl(request.getCardFrontUrl()));
        request.setCardBackUrl(OSSFixUtils.fixOssUrl(request.getCardBackUrl()));
        request.setHandHeldUrl(OSSFixUtils.fixOssUrl(request.getHandHeldUrl()));
        request.setPanCardUrl(OSSFixUtils.fixOssUrl(request.getPanCardUrl()));
        long s = System.currentTimeMillis();
        this.saveCard(request);
        LOGGER.info("== save card log ==,cost:{}", System.currentTimeMillis() - s);
    }

    private void saveCard(AadhaarCardSaveRequest request) {
        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        UserKycAadhaarInfo userKycAadhaarInfo = null;
        //ocr
        if (apolloConfigUtil.openCheckAadhaar()) {
            if (UserKycTypeEnum.AADHAAR.getType().equals(String.valueOf(request.getType()))) {
                LOGGER.info("== save card log ==aadhaar request userCode:{}, openApiOcr:{}", userCode, apolloConfigUtil.openApiOcr());
                String ocrData = asyncService.asyncOcrV3(UserOcrTypeEnum.AADHAAR_FRONT, request.getCardFrontUrl(), request.getCardBackUrl(), userCode);
                if (StringUtils.isNotEmpty(ocrData)) {
                    LOGGER.info("== save card log == AADHAAR信息,userCode:{},ocrData:{}", userCode, ocrData);
                    Date birthday = null;
                    String ocrCardNo = null;
                    String name = null;
                    try {
                        JSONObject jsonObject = JSON.parseObject(ocrData);
                        JSONObject card = jsonObject.getJSONArray("results").getJSONObject(0).getJSONObject("card_info");
                        String dateInfo = card.getString("date_info");
                        ocrCardNo = card.getString("card_no");
                        name = card.getString("name");
                        birthday = this.getAadhaarBirthday(dateInfo);

                        userKycAadhaarInfo = new UserKycAadhaarInfo();
                        userKycAadhaarInfo.setUserCode(userCode);
                        userKycAadhaarInfo.setAadhaarType(dateInfo.length() == 4 ? "old" : "new");
                        userKycAadhaarInfo.setAddress(card.getString("address"));
                        userKycAadhaarInfo.setAddressLineOne(card.getString("address_line_one"));
                        userKycAadhaarInfo.setAddressLineTwo(card.getString("address_line_two"));
                        userKycAadhaarInfo.setCardNo(card.getString("card_no"));
                        userKycAadhaarInfo.setCareOf(card.getString("care_of"));
                        userKycAadhaarInfo.setCity(card.getString("city"));
                        userKycAadhaarInfo.setDateInfo(card.getString("date_info"));
                        userKycAadhaarInfo.setDateType(card.getString("date_type"));
                        userKycAadhaarInfo.setDaughterOf(card.getString("daughter_of"));
                        userKycAadhaarInfo.setGender(card.getString("gender"));
                        userKycAadhaarInfo.setHusbandOf(card.getString("husband_of"));
                        userKycAadhaarInfo.setMotherName(card.getString("mother_name"));
                        userKycAadhaarInfo.setName(card.getString("name"));
                        userKycAadhaarInfo.setNeedCheck(card.getString("need_check"));
                        userKycAadhaarInfo.setPhoneNumber(card.getString("phone_number"));
                        userKycAadhaarInfo.setPin(card.getString("pin"));
                        userKycAadhaarInfo.setSonOf(card.getString("son_of"));
                        userKycAadhaarInfo.setState(card.getString("state"));
                        userKycAadhaarInfo.setVid(card.getString("vid"));
                        userKycAadhaarInfo.setWifeOf(card.getString("wife_of"));
                    } catch (Exception e) {
                        LOGGER.error("== save card log == AADHAAR解析ocrData失败,userCode:{}", userCode, e);
                        throw new ApplicationException("Aadhaar photo is not clear, please upload the photo again.");
                    }

                    if (apolloConfigUtil.saveCardInfoCompare()) {
                        //ocr必要参数校验
                        if (birthday == null) {
                            LOGGER.error("== save card log == aadhaar front 照片识别失败,userCode:{},ocrData:{}", userCode, ocrData);
                            throw new ApplicationException("Aadhaar photo is not clear, please upload the photo again.");
                        }
                        if (StringUtils.isEmpty(name)) {
                            LOGGER.warn("== save card log == aadhaar front 照片姓名失败,userCode:{},ocrData:{}", userCode, ocrData);
                            throw new ApplicationException("Aadhaar photo is not clear, please upload the photo again.");
                        }
                        if (!request.getCardNo().equalsIgnoreCase(ocrCardNo)) {
                            LOGGER.error("== save card log == AADHAAR front 卡号识别失败,userCode:{},cardNo:{},ocrCardNo:{},ocrData:{}", userCode, request.getCardNo(), ocrCardNo, ocrData);
                            throw new ApplicationException("Aadhaar number is different from photo, please enter the correct content.");
                        }
                    }
                }
            }
        }

        //保存kyc信息
        UserKycDocumentInfo userKycDocumentInfo = new UserKycDocumentInfo();
        userKycDocumentInfo.setUserCode(userCode);
        userKycDocumentInfo.setAuthType(UserKycTypeEnum.getEnumByStatus(String.valueOf(request.getType())));
        userKycDocumentInfo.setCardBackUrl(request.getCardBackUrl());
        userKycDocumentInfo.setCardFrontUrl(request.getCardFrontUrl());
        userKycDocumentInfo.setHandHoldUrl(request.getHandHeldUrl());
        userKycDocumentInfo.setCardId(request.getCardNo().toUpperCase());
        userKycDocumentInfo.setUserKycAadhaarInfo(userKycAadhaarInfo);
        userKycDocumentService.saveUserKycInfo(userKycDocumentInfo);
        LOGGER.info("== save card log ==kyc保存成功,userCode:{}", userCode);

        userEventTrackService.e_app_idcard_done();

        if (apolloConfigUtil.openCheckAadhaar()) {
            String panCardOcrData = asyncService.asyncOcrV3(UserOcrTypeEnum.PAN_FRONT, request.getPanCardUrl(), null, userCode);
            if (StringUtils.isNotEmpty(request.getPanCardUrl())) {
                String panCardNo = request.getPanCardNo();
                LOGGER.info("== save card log ==panCardOcr信息,userCode:{},panCardOcrData:{}", userCode, panCardOcrData);
                Date birthday = null;
                String ocrCardNo = null;
                String name = null;
                try {
                    JSONObject jsonObject = JSON.parseObject(panCardOcrData);
                    JSONObject card = jsonObject.getJSONArray("results").getJSONObject(0).getJSONObject("card_info");
                    ocrCardNo = card.getString("card_no");
                    name = card.getString("name");
                    birthday = getPanBirthday(card.getString("date_info"));
                } catch (Exception e) {
                    LOGGER.error("== save card log ==解析ocrData失败,userCode:{}", userCode, e);
                    throw new ApplicationException("Pan Card photo is not clear, please upload the photo again.");
                }

                if (apolloConfigUtil.saveCardInfoCompare()) {
                    //ocr必要参数校验
                    if (birthday == null) {
                        LOGGER.warn("== save card log ==birthrday 照片识别失败,userCode:{},ocrData:{}", userCode, panCardOcrData);
                        throw new ApplicationException("Pan Card photo is not clear, please upload the photo again.");
                    }
                    if (StringUtils.isEmpty(name)) {
                        LOGGER.warn("== save card log == name 照片识别失败,userCode:{},ocrData:{}", userCode, panCardOcrData);
                        throw new ApplicationException("Pan Card photo is not clear, please upload the photo again.");
                    }
                    if (!panCardNo.equalsIgnoreCase(ocrCardNo)) {
                        LOGGER.warn("== save card log == Pan卡号识别失败,userCode:{},cardNo:{},ocrCardNo:{},ocrData:{}", userCode, panCardNo, ocrCardNo, panCardOcrData);
                        throw new ApplicationException("Pan number is different from photo, please enter the correct content.");
                    }
                    //Pan 和 Aadhaar 生日交叉验证
//                Response<List<UserKycDocumentInfo>> userKycDocumentResponse = userKycDocumentService.getByUserCode(userCode);
//                if (userKycDocumentResponse != null && userKycDocumentResponse.isSuccess()
//                        && com.fqgj.common.utils.CollectionUtils.isNotEmpty(userKycDocumentResponse.getData())) {
//                    //如果aadhaar的数据对象不为空 则和pan进行生日校验
//                    if (userKycAadhaarInfo != null) {
//                        LOGGER.info("Pan和Aadhaar生日交叉验证,userCode:{},birthday:{},userKycAadhaarInfo:{}", userCode, DateUtil.getDate(birthday), JSON.toJSONString(userKycAadhaarInfo));
//                        Date aadhaarBirthday = this.getAadhaarBirthday(userKycAadhaarInfo.getDateInfo());
//                        if (aadhaarBirthday != null) {
//                            if ("old".equals(userKycAadhaarInfo.getAadhaarType())) {
//                                if (!Objects.equals(DateUtil.getDate(birthday, "yyyy"), DateUtil.getDate(aadhaarBirthday, "yyyy"))) {
//                                    throw new ApplicationException("PAN and AADHAAR have different birthdays, Please upload a clear photo again.");
//                                }
//                            } else if ("new".equals(userKycAadhaarInfo.getAadhaarType())) {
//                                if (!Objects.equals(birthday, aadhaarBirthday)) {
//                                    throw new ApplicationException("PAN and AADHAAR have different birthdays, Please upload a clear photo again.");
//                                }
//                            }
//                        }
//                    }
//                }
                }

                if (birthday != null) {
                    UserBase userBase = new UserBase();
                    userBase.setUserCode(userCode)
                            .setBirthday(com.fqgj.common.utils.DateUtil.getDate(birthday, "yyyy-MM-dd"));
                    userInfoService.updateUserBase(userBase);
                    LOGGER.info("== save card log == 更新birthday,userCode:{},userBase:{}", userCode, userBase.getBirthday());
                }
            }
        }
        String panCardUrl = OSSFixUtils.fixOssHttpUrl(request.getPanCardUrl());
        //保存panCard
        UserPanSaveInfo userPanSaveInfo = new UserPanSaveInfo();
        userPanSaveInfo.setUserCode(userCode);
        userPanSaveInfo.setCardUrl(panCardUrl);
        userPanSaveInfo.setCardNo(request.getPanCardNo());
        userPanSaveInfo.setPanStatus("Y");  // 主要用于校验信息完整性
        userPanService.addUserPan(userPanSaveInfo);
        LOGGER.info("== save card log == pancard保存成功,userCode:{},panCardUrl:{}", userCode, panCardUrl);
    }

    /**
     * 尝试解析生日
     *
     * @param dob
     * @return
     */
    public Date getPanBirthday(String dob) {
        if (org.apache.commons.lang3.StringUtils.isEmpty(dob)) {
            return null;
        }
        Date birthday = null;

        try {
            if (dob.contains("/")) {
                birthday = DateUtil.getDate(dob, "dd/MM/yyyy");
            } else if (dob.contains("-")) {
                birthday = DateUtil.getDate(dob, "dd-MM-yy");
            } else {
                birthday = DateUtil.getDate(dob, "ddMMyyyy");
            }
            if (birthday.getTime() < com.fqgj.common.utils.DateUtil.getDate("1950-01-01", "yyyy-MM-dd").getTime()
                    || birthday.getTime() > System.currentTimeMillis()) {
                LOGGER.error("异常生日,date:{}", dob);
                return null;
            }
            LOGGER.info("解析得到生日,{}", DateUtil.getDate(birthday));
        } catch (Exception e) {
            LOGGER.info("尝试解析生日失败,{}", dob, e);
        }

        return birthday;
    }

    /**
     * 尝试解析生日
     *
     * @param dob
     * @return
     */
    public Date getAadhaarBirthday(String dob) {
        if (StringUtils.isEmpty(dob)) {
            return null;
        }
        Date birthday = null;

        try {
            //旧版本Aadhaar
            if (dob.length() == 4 && !dob.contains("/") && !dob.contains("-")) {
                birthday = DateUtil.getDate(dob + "0101", "yyyyMMdd");
                LOGGER.info("旧版本Aadhaar得到出生年,{}", DateUtil.getDate(birthday));
            } else {
                //新版本Aadhaar
                if (dob.contains("/")) {
                    birthday = DateUtil.getDate(dob, "dd/MM/yyyy");
                } else if (dob.contains("-")) {
                    birthday = DateUtil.getDate(dob, "dd-MM-yy");
                } else {
                    birthday = DateUtil.getDate(dob, "ddMMyyyy");
                }
                LOGGER.info("新版本Aadhaar得到生日,{}", DateUtil.getDate(birthday));
            }
            if (birthday.getTime() < com.fqgj.common.utils.DateUtil.getDate("1950-01-01", "yyyy-MM-dd").getTime()
                    || birthday.getTime() > System.currentTimeMillis()) {
                LOGGER.error("异常生日,date:{}", dob);
                return null;
            }
        } catch (Exception e) {
            LOGGER.info("尝试解析生日失败,{}", dob, e);
        }

        return birthday;
    }

    private void validate(AadhaarCardSaveRequest request) {
        if (StringUtils.isEmpty(request.getCardNo())) {
            throw new ApplicationException("Required items can not be empty");
        }
        if (request.getType() == null || request.getType() == 0) {
            throw new ApplicationException("type is empty");
        }
        if (StringUtils.isEmpty(request.getCardFrontUrl())) {
            throw new ApplicationException("Please upload ID picture");
        }
        if (StringUtils.isEmpty(request.getCardBackUrl())) {
            throw new ApplicationException("Please upload ID picture");
        }
        if (StringUtils.isEmpty(request.getHandHeldUrl())) {
            throw new ApplicationException("Please upload ID picture");
        }
        if (StringUtils.isEmpty(request.getPanCardNo())) {
            throw new ApplicationException("please select document");
        }
        if (StringUtils.isEmpty(request.getPanCardUrl())) {
            throw new ApplicationException("Please upload PanCard picture");
        }
        if (StringUtils.isNotEmpty(request.getPanCardNo()) && StringUtils.isNotEmpty(request.getPanCardUrl())) {
            String reg = "[a-zA-Z]{3}[P,H][a-zA-Z][0-9]{4}[a-zA-Z]";
            String panCardNo = request.getPanCardNo().replaceAll("(\\r\\n|\\t|\\\\r|\\\\n\\\\t|\n|\n\t|\r|\r\n|\t)", "");
            boolean matchFlag = panCardNo.matches(reg);
            if (!matchFlag) {
                throw new ApplicationException("Please enter the correct PanCard number");
            }
        }
        LOGGER.info("======== type:{},cardNo:{} ============", request.getType(), request.getCardNo());
        if (Objects.equals(UserKycTypeEnum.AADHAAR.getType(), String.valueOf(request.getType()))) {
            String aadhaarReg = "[0-9]{12}";
            String cardNo = request.getCardNo().replaceAll("(\\r\\n|\\t|\\\\r|\\\\n\\\\t|\n|\n\t|\r|\r\n|\t)", "");
            if (!cardNo.matches(aadhaarReg)) {
                throw new ApplicationException("Please enter correct AADHAAR NO.");
            }
        }

        if (Objects.equals(UserKycTypeEnum.PASSPORT.getType(), String.valueOf(request.getType()))) {
            String passportReg = "[a-zA-Z][0-9]{7}";
            String cardNo = request.getCardNo();
            if (!cardNo.matches(passportReg)) {
                throw new ApplicationException("Please enter correct PASSPORT");
            }
        }

        if (Objects.equals(UserKycTypeEnum.VOTER_ID.getType(), String.valueOf(request.getType()))) {
            String voterIdReg = "[a-zA-Z]{3}[0-9]{7}";
            String cardNo = request.getCardNo();
            if (!cardNo.matches(voterIdReg)) {
                throw new ApplicationException("Please enter correct VOTER ID");
            }
        }
    }
}
